#include "transContentThreads.hpp"

int TransContentThreadPool::addTask(Task insTask){
	return addTask(insTask.iWork, insTask.iParam);
}

int TransContentThreadPool::addTask(work iwork, void* p){
	if(mWrokCount == mtaskListCapacity && mtaskListCapacity >= THREAD_TASK_COUNT_MAX){
		logd_error("new worker, the task list is full");
		return E_TRANC_BUFFER_FULL;
	}   
	if(mWrokCount == mtaskListCapacity){
		mtaskListCapacity = 2 * mtaskListCapacity;
		taskList = relloc(taskList, mtaskListCapacity);
	}   
	logd_info("start to insert new task");
	pthread_mutex_lock(&poolMutex);
	for(int i=0; i< mtaskListCapacity; ++i){
		if(taskList[i].iWork == NULL){
			mWrokCount++;
			taskList[i].iWork = iWork;
			taskList[i].iParam = p;
			pthread_cond_signal(poolCondtion);
			break;
		}   
	}   
	return E_TRANC_SUCESS;
}

int TransContentThreadPool::removeTask(void* p){
	debug_enter();
	pthread_mutex_lock(&poolMutex);
	for(int i=0, count=0; i< mtaskListCapacity && count <= mWrokCount; ++i){
		if(taskList[i].iWork != NULL){
			++count;
			if(taskList[i].iParam == p){
				logd_info("threads pool, remore a task");
				--mWrokCount;
				taskList[i].iWork = NULL;
				taskList[i].iParam = NULL;
			}
		}
	}
	debug_leave();
	return E_TRANC_SUCESS;
}

int TransContentThreadPool::createThreads(){ 
	debug_enter();
	if(mState == INS_STATE_ERROR){
		logd_info("start to create threads");
		for(int i=0; i< mThreadCount; ++i){
			pthread_create(&threads[i], NULL, threadRoute, NULL);
		}
		logd_info("thread pool, create threads end, total create %d count", mThreadCount);
		mState = INS_STATE_OK;
		pthread_create(&threadCheck, NULL, threadCheckRoute, this);
		pthread_detach(threadCheck);
	}
	debug_leave();
	return E_TRANC_SUCESS;
}

int TransContentThreadPool::destroyThreads(){
	pthread_cond_boardcast(poolCondtion);                                                                                       
	if(mState == INS_STATE_ERROR){
		logd_warmming("thread pool, start to destroy all threads");
		for(int i=0; i<mThreadCount; ++i){
			pthread_cancel(threads[i]);
			pthread_join(threads[i]);                   
		}
	}
}

void TransContentThreadPool::threadRouteIns(){
	task iTask;
	debug_enter();
	while(mState == INS_STATE_OK){
		// wait to get a work
		pthread_mutex_lock(&poolMutex);
		while(mWrokCount == 0){
			pthread_cond_wait(&poolCondtion, &poolMutex);
			if(mState != INS_STATE_OK){
				pthread_mutex_unlock(&poolMutex);
				logd_info("thread route ins, the thread pool instance should return");
				return;
			}
		}

		iTask = getATask();
		// test whether has more task to work
		if(mWorkCount > 0){
			logd_info("the thread get a task, the there still are more works left");
			pthread_cond_signal(&poolCondtion);
		}
		pthread_mutex_unlock(&poolMutex);

		if(iTask.iWork == NULL){
			logd_info("thread pool, get a task, but the task route is NULL, continue wait avaliable one");
			continue;
		}

		// stack to work
		logd_info("the thread task start to work");
		iTask.iwork(iTask.iParam);
		logd_info("the thread task end!");
	}
	debug_leave();
}

void TransContentThreadPool::threadCheckRouteIns(){
	while(mState == INS_STATE_OK){
		for(int i=0; i< mThreadCount; ++i){
			if(pthread_kill(threads[i], 0) == ESRCH){
				logd_info("thread check, the thread id=%d not exist any more, create a new one");
				pthread_join(threads[i]);
				pthread_create(&threads[i], NULL, threadRoute, NULL);
			}
		}
		sleep(THREADS_EXIST_CHECK_INTERVAL);
	}
}
